Version 3 (modified by guest, 15 years ago) (diff) |
---|
These snippets should be useful to read RAR archives with store compression (which means none compression is used). Feel free to edit/add source-codes if you have faster/better/new language implementation.
Links:
- http://www.unrarlib.org/
- http://www.rarlab.com/rar_add.htm
- http://github.com/jphastings/unrar/ (in Ruby)
Python
#(c)Kamil Dzióbek turbos11(at)gmail.com # BSD License from struct import * def getlastsplit(firsrarfile,x): if firsrarfile[-3:]=='001': return firsrarfile[:-3]+('%03d' %(x+1)) if firsrarfile[-11:-6]=='.part': return firsrarfile[0:-6]+('%02d' % (x+1))+firsrarfile[-4:] if firsrarfile[-10:-5]=='.part': return firsrarfile[0:-5]+('%1d' % (x+1))+firsrarfile[-4:] return firsrarfile[0:-2]+('%02d' %(x-1) ) def addfilehash(name,hash,seek): f=open(name, 'rb') f.seek(seek) for i in range(8192): hash+=unpack('<q', f.read(8))[0] hash =hash & 0xffffffffffffffff return hash def OpensubtitlesHashRar(firsrarfile): """Hash file in rar split archive. -> (size,hash)""" if not(firsrarfile.lower().endswith('.rar') | firsrarfile.endswith('.001')): raise Exception('Bad file suffix. Only .rar and .001 support.') if firsrarfile[-11:-6]=='.part': firsrarfile=firsrarfile[0:-6]+'01'+firsrarfile[-4:] f=open(firsrarfile, 'rb') a=f.read(4) if a!='Rar!': raise Exception('ERROR: This is not rar file.') seek=0 for i in range(4): f.seek(seek) a=f.read(100) type,flag,size=unpack( '<BHH', a[2:2+5]) if 0x74==type: if 0x30!=unpack( '<B', a[25:25+1])[0]: raise Exception('Bad compression method! Work only for "store".') s_partiizebodystart=seek+size s_partiizebody,s_unpacksize=unpack( '<II', a[7:7+2*4]) if (flag & 0x0100): s_unpacksize=(unpack( '<I', a[36:36+4])[0] <<32 )+s_unpacksize print 'Hash untested for files biger that 2gb. May work or may generate bad hash.' lastrarfile=getlastsplit(firsrarfile,(s_unpacksize-1)/s_partiizebody) hash=addfilehash(firsrarfile,s_unpacksize,s_partiizebodystart) hash=addfilehash(lastrarfile,hash,(s_unpacksize%s_partiizebody)+s_partiizebodystart-65536) return (s_unpacksize,"%016x" % hash ) seek+=size raise Exception('ERROR: Not Body part in rar file.') #example firsrarsplitfile='I:\\test.rar' size,hash=OpensubtitlesHashRar(firsrarsplitfile) print 'use this valuse on opensubtiles.com\n\tsize is: %d\n\thash is: %s' % (size,hash)
Ruby
Noncomplete translation of Python-code.
def getlastsplit(firsrarfile, x) return firsrarfile[0..-3] + ('%03d' % (x+1)) if firsrarfile[-3..-1] == '001' return firsrarfile[0..-6] + ('%02d' % (x+1)) + firsrarfile[-4..-1] if firsrarfile[-11..-6] == '.part' return firsrarfile[0..-5] + ('%1d' % (x+1)) + firsrarfile[-4..-1] if firsrarfile[-10..-5] == '.part' return firsrarfile[0..-2] + ('%02d' % (x-1)) end def addfilehash(name, hash, seek) f = File.open(name, 'rb') f.seek(seek) 8192.times do |i| hash += f.read(8).unpack('q')[0] hash = hash & 0xffffffffffffffff end return hash end # Hash file in rar split archive. -> (size,hash) def OpensubtitlesHashRar(firsrarfile) raise 'Bad file suffix. Only .rar and .001 support.' unless firsrarfile.downcase =~ /\.rar$/ || firsrarfile =~ /\.001$/ firsrarfile = firsrarfile[0..-6] + '01' + firsrarfile[-4..-1] if firsrarfile[-11..-6] == '.part' f = File.open(firsrarfile, 'rb') a = f.read(4) raise 'ERROR: This is not rar file.' if a != 'Rar!' seek = 0 4.times do |i| f.seek(seek) a = f.read(100) type, flag, size = a[2..7].unpack('Cvv') puts [type, flag, size].inspect if 0x74 == type raise 'Bad compression method! Work only for "store".' if 0x30 != a[25..26].unpack('C')[0] s_partiizebodystart = seek + size s_partiizebody, s_unpacksize = a[7..15].unpack('<II') if flag & 0x0100 s_unpacksize = (a[36..40].unpack('<I')[0] << 32) + s_unpacksize puts 'Hash untested for files biger that 2gb. May work or may generate bad hash.' end lastrarfile = getlastsplit(firsrarfile, (s_unpacksize-1) / s_partiizebody) hash = addfilehash(firsrarfile, s_unpacksize, s_partiizebodystart) hash = addfilehash(lastrarfile, hash, (s_unpacksize % s_partiizebody) + s_partiizebodystart - 65536) return [s_unpacksize, "%016x" % hash] end seek += size end raise 'ERROR: Not Body part in rar file.' end #example firsrarsplitfile=ARGV[0] size, hash = OpensubtitlesHashRar(firsrarsplitfile) puts('use this valuse on opensubtiles.com\n\tsize is: %d\n\thash is: %s' % [size, hash])